using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;

namespace Library.IniFiles
{
    public class IniFile
    {
        private SortedList<string, IniSection> sections;
        private List<IniSection> orderedSections = new List<IniSection>();
        private string fileName;
        private bool allowEmptySections = false;
        private bool indexerOverwrites = false;

        public IniFile() {}

        public ReadOnlyCollection<IniSection> OrderedSections
        {
            get
            {
                return orderedSections.AsReadOnly();
            }
        }

        public IniSection this[string title]
        {
            get
            {
                IniSection s = null;
                if (!Sections.ContainsKey(title))
                {
                    s = new IniSection(title);
                    s.IniFile = this;
                    Sections[title] = s;

                    orderedSections.Add(s);
                }
                else
                {
                    s = Sections[title];
                }
                return s;
            }
            set
            {
                if (value == null)
                {
                    if (this.Sections.ContainsKey(title))
                    {
                        if (this.orderedSections.Contains(Sections[title])) orderedSections.Remove(Sections[title]);
                        Sections.Remove(title);
                    }
                }
                else
                {
                    value.IniFile = this;
                    if (!this.orderedSections.Contains(value)) orderedSections.Add(value);

                    Sections[title] = value;
                }
            }
        }

        public bool HasHeaderSection
        {
            get
            {
                if (Sections.ContainsKey(IniSection.HEADER_SECTION_TITLE))
                {
                    return (Sections[IniSection.HEADER_SECTION_TITLE].KeyValuesCollection.Count > 0);
                }
                return false;
            }
        }

        public IniSection HeaderSection
        {
            get
            {
                if (!Sections.ContainsKey(IniSection.HEADER_SECTION_TITLE))
                {
                    Sections[IniSection.HEADER_SECTION_TITLE] = new IniSection(IniSection.HEADER_SECTION_TITLE);
                }
                return Sections[IniSection.HEADER_SECTION_TITLE];
            }
        }

        public SortedList<string, IniSection> Sections
        {
            get
            {
                if (sections == null)
                {
                    sections = new SortedList<string, IniSection>();
                }
                return sections;
            }
        }

        public bool AllowEmptySections
        {
            get
            {
                return allowEmptySections;
            }
            set
            {
                allowEmptySections = value;
            }
        }

        public bool IndexerOverwrites
        {
            get
            {
                return indexerOverwrites;
            }
            set
            {
                indexerOverwrites = value;
            }
        }

        public void Load(string fileName)
        {
            this.fileName = fileName;

            IniFileReader iniReader = new IniFileReader();
            iniReader.ItemRead += new EventHandler<IniReaderEventArgs>(IniReader_ItemRead);
            iniReader.Read(fileName);
        }

        private void IniReader_ItemRead(object sender, IniReaderEventArgs e)
        {
            if (!e.IsSectionHeader && !e.IsFullLineComment) 
            {
                if (!this[e.SectionTitle].KeyValuesCollection.ContainsKey(e.Key))
                {
                    this[e.SectionTitle].KeyValuesCollection[e.Key] = new List<string>();
                }

                foreach (string value in e.Values)
                {
                    this[e.SectionTitle].KeyValuesCollection[e.Key].Add(value);
                }
            }
            else if (e.IsSectionHeader && AllowEmptySections)
            {
                IniSection s = this[e.SectionTitle];
            }
        }

        public void Save()
        {
            this.Save(fileName);
        }

        public void Save(string fileName)
        {
            IniFileWriter.Write(fileName, this);
        }

        public void Save(string fileName, bool writeEmptySections)
        {
            IniFileWriter.Write(fileName, this, writeEmptySections);
        }
    }
}
